package com.wugh.fast.module.mapper.interceptor;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.wugh.fast.kernel.core.exception.FastGlobalException;
import com.wugh.fast.kernel.core.util.SpelUtils;
import com.wugh.fast.module.mapper.DynamicSchemaStorage;
import com.wugh.fast.module.mapper.anno.DynamicSchema;
import com.wugh.fast.module.mapper.service.DynamicSchemaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.lang.reflect.Method;

/**
 * 说明: 通过DynamicSchema注解,动态设置数据库schema
 *
 * @author wugh
 * @date 2019-12-31 17:11
 */
@Slf4j
@Aspect
public class DynamicSchemaAspect {
    @Around(value = "@annotation(com.wugh.fast.module.mapper.anno.DynamicSchema)")
    public Object dynamicSetSchema(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        DynamicSchema annotation = AnnotationUtils.getAnnotation(method, DynamicSchema.class);
        String value = annotation.value();
        if (StringUtils.isBlank(value)) {
            throw new FastGlobalException(StrUtil.format("[{}]方法未设置动态Schema的Spel表达式", getCaller(joinPoint)));
        }
        SpelExpressionParser parser = SpelUtils.getExpressionParser();
        EvaluationContext context = SpelUtils.createEvaluationContext(joinPoint);
        String schema = parser.parseExpression(value).getValue(context, String.class);
        return DynamicSchemaStorage.templateSwitch(schema, (s) -> {
            try {
                return joinPoint.proceed();
            } catch (Throwable throwable) {
                throw ExceptionUtil.wrapRuntime(throwable);
            }
        });
    }

    public static String getCaller(ProceedingJoinPoint pjp) {
        // 获取简单类名
        String className = pjp.getSignature().getDeclaringTypeName();
        String simpleClassName = className.substring(className.lastIndexOf(".") + 1);
        // 获取方法名
        String methodName = pjp.getSignature().getName();
        return simpleClassName + "#" + methodName;
    }
}
